package com.lj.queue.handler;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.lj.common.exception.CommonException;
import com.lj.queue.entity.DelayQueueMessage;
import lombok.Data;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @author luojing
 * @since 2025/7/16 18:44
 * 延迟消息，最终所有的消息都要包装成该类投入到延迟队列中
 */
@Data
public class DelayedMessage implements Delayed {

    /**
     * 预计执行时间
     */
    private LocalDateTime expectTime;

    /**
     * 队列id
     */
    private Long queueId;

    /**
     * 消息id
     */
    private Long messageId;

    /**
     * 消息内容
     */
    private String message;

    private DelayedMessage() {
    }

    public static DelayedMessage of(DelayQueueMessage message) {
        if (message == null || message.getExpectTime() == null) {
            throw new CommonException("消息的期望执行时间不能为空!");
        }
        return of(message.getExpectTime())
                .setQueueId(message.getQueueId())
                .setMessageId(message.getId())
                .setMessage(message.getMessage());
    }

    public static DelayedMessage of(LocalDateTime expectTime) {
        return new DelayedMessage().setExpectTime(expectTime);
    }

    public DelayedMessage setExpectTime(LocalDateTime expectTime) {
        this.expectTime = expectTime;
        return this;
    }

    public DelayedMessage setQueueId(Long queueId) {
        this.queueId = queueId;
        return this;
    }

    public DelayedMessage setMessageId(Long messageId) {
        this.messageId = messageId;
        return this;
    }

    public DelayedMessage setMessage(String message) {
        this.message = message;
        return this;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(LocalDateTimeUtil.between(LocalDateTime.now(), expectTime, ChronoUnit.NANOS), TimeUnit.NANOSECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        DelayedMessage other = ((DelayedMessage) o);
        if (this.expectTime.isEqual(other.expectTime)) {
            return 0;
        }
        if (this.expectTime.isBefore(other.expectTime)) {
            return -1;
        }
        return 1;
    }


}
